use std::sync::atomic::{AtomicI32, Ordering};
use tokio::sync::mpsc::{Sender};
use crate::protoHeader::ProtoHeader;
use crate::ProtoId::ProtoID;
use std::fmt::format;

#[derive(PartialEq)]
pub enum ConnStatus {
    START,
    CONNECTING,
    CONNECTED,
    READY,
    CLOSED,
}

pub struct Proto_sender {
    atomic_int: AtomicI32,
    // connStatus: ConnStatus,
    // sentProtoMap:HashMap<i32,SentProtoData>,
    protoTx: Sender<Vec<u8>>,
}

impl Proto_sender {
    pub fn new(tx: Sender<Vec<u8>>) -> Proto_sender {
        Proto_sender {
            atomic_int: AtomicI32::new(1),
            // connStatus: ConnStatus::READY,
            // connStatus: ConnStatus::START,
            // sentProtoMap: HashMap::new(),
            protoTx: tx,
        }
    }

    pub async fn sendProto<T: prost::Message>(&self, protoId: ProtoID, req: &T) -> Result<ProtoHeader, String> {
        let mut body = Vec::new();
        req.encode(&mut body).unwrap();

        // let serialNO = self.atomic_int.fetch_add(1, Ordering::Relaxed);
        let serialNO = 13;
        let header = ProtoHeader::new(protoId as i32, &body[..], serialNO);

        let headerBuffer = header.write().or(Err(std::fmt::format(format_args!("header serialize failed. protoID:{:?}", protoId))))?;
        let headerSize = headerBuffer.len();
        let mut bufferVec = vec![0; headerSize + body.len()];

        bufferVec[..headerSize].copy_from_slice(&headerBuffer[..]);
        bufferVec[headerSize..].copy_from_slice(&body[..]);

        self.protoTx.send(bufferVec).await.and(Ok(header)).or(Err(format(format_args!("send proto failed. protoID:{:?}", protoId))))
    }
}